package org.futo.inputmethod.updates

import android.app.job.JobInfo
import android.app.job.JobScheduler
import android.content.ComponentName
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.datastore.preferences.core.edit
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
//import okhttp3.OkHttpClient
//import okhttp3.Request
//import okhttp3.internal.closeQuietly
import org.futo.inputmethod.latin.uix.dataStore
import org.futo.inputmethod.latin.uix.getSetting
import org.futo.inputmethod.latin.BuildConfig
import java.lang.Exception

const val UPDATE_URL = "https://keyboard.futo.org/keyboard_version"

suspend fun checkForUpdate(): UpdateResult? {
    if(!BuildConfig.UPDATE_CHECKING || !BuildConfig.UPDATE_CHECKING_NETWORK) return null
    else return null

    // TODO: Move this code to a different source directory so we can enable or disable
    // it per build flavor (e.g. so nightly can have update checking)
    /*
    return withContext(Dispatchers.IO) {
        val httpClient = OkHttpClient()

        val request = Request.Builder().method("GET", null).url(UPDATE_URL).build()

        try {
            val response = httpClient.newCall(request).execute()

            val body = response.body
            val result = if (body != null) {
                val data = body.string().lines()
                body.closeQuietly()

                val latestVersion = data[0].toInt()
                val latestVersionUrl = data[1]
                val latestVersionString = data[2]
                if(latestVersionUrl.startsWith("https://voiceinput.futo.org/") || latestVersionUrl.startsWith("https://keyboard.futo.org/")){
                    Log.d("UpdateChecking", "Retrieved update for version ${latestVersionString}")
                    UpdateResult(
                        nextVersion = latestVersion,
                        apkUrl = latestVersionUrl,
                        nextVersionString = latestVersionString
                    )
                } else {
                    Log.e("UpdateChecking", "Update URL contains unknown prefix: ${latestVersionUrl}")
                    null
                }
            } else {
                Log.e("UpdateChecking", "Body of result is null")
                null
            }

            response.closeQuietly()

            result
        } catch (e: Exception) {
            Log.e("UpdateChecking", "Checking update failed with exception")
            e.printStackTrace()
            null
        }
    }*/
}

suspend fun checkForUpdateAndSaveToPreferences(context: Context): Boolean {
    val updateResult = checkForUpdate()
    if(updateResult != null) {
        withContext(Dispatchers.IO) {
            context.dataStore.edit {
                it[LAST_UPDATE_CHECK_RESULT] = Json.encodeToString(updateResult)
                it[LAST_UPDATE_CHECK_FAILED] = false
                it[DEFER_MANUAL_UPDATE_UNTIL] = System.currentTimeMillis() + MANUAL_UPDATE_PERIOD_MS
            }
        }
        return true
    } else {
        context.dataStore.edit {
            it[LAST_UPDATE_CHECK_FAILED] = true

            if(it[DEFER_MANUAL_UPDATE_UNTIL] == null) {
                it[DEFER_MANUAL_UPDATE_UNTIL] = System.currentTimeMillis() + MANUAL_UPDATE_PERIOD_MS
            }
        }

        return false
    }
}

suspend fun retrieveSavedLastUpdateCheckResult(context: Context): UpdateResult? {
    if(!BuildConfig.UPDATE_CHECKING) return null

    return UpdateResult.fromString(context.getSetting(LAST_UPDATE_CHECK_RESULT, ""))
}

const val JOB_ID: Int = 15782788
fun scheduleUpdateCheckingJob(context: Context) {
    if(!BuildConfig.UPDATE_CHECKING_NETWORK) return

    val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler

    if(jobScheduler.getPendingJob(JOB_ID) != null) {
        Log.i("UpdateChecking", "Job already scheduled, no need to do anything")
        return
    }

    var jobInfoBuilder = JobInfo.Builder(JOB_ID, ComponentName(context, UpdateCheckingService::class.java))
        .setPeriodic(1000L * 60L * 60L * 12L) // every 12 hours
        //.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) // on unmetered Wi-Fi
        .setPersisted(true) // persist after reboots

    // Update checking has minimum priority
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        jobInfoBuilder = jobInfoBuilder.setPriority(JobInfo.PRIORITY_MIN)
    }

    jobScheduler.schedule(jobInfoBuilder.build())
}